home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-MIPS / CHECKSUM.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  5KB  |  256 lines

  1. /* $Id: checksum.h,v 1.6 1998/09/16 13:30:51 ralf Exp $
  2.  *
  3.  * This file is subject to the terms and conditions of the GNU General Public
  4.  * License.  See the file "COPYING" in the main directory of this archive
  5.  * for more details.
  6.  *
  7.  * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
  8.  */
  9. #ifndef __ASM_MIPS_CHECKSUM_H
  10. #define __ASM_MIPS_CHECKSUM_H
  11.  
  12. /*
  13.  * computes the checksum of a memory block at buff, length len,
  14.  * and adds in "sum" (32-bit)
  15.  *
  16.  * returns a 32-bit number suitable for feeding into itself
  17.  * or csum_tcpudp_magic
  18.  *
  19.  * this function must be called with even lengths, except
  20.  * for the last fragment, which may be odd
  21.  *
  22.  * it's best to have buff aligned on a 32-bit boundary
  23.  */
  24. unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
  25.  
  26. /*
  27.  * this is a new version of the above that records errors it finds in *errp,
  28.  * but continues and zeros the rest of the buffer.
  29.  */
  30. #define csum_partial_copy_nocheck csum_partial_copy
  31.  
  32. /*
  33.  * this is a new version of the above that records errors it finds in *errp,
  34.  * but continues and zeros the rest of the buffer.
  35.  */
  36. unsigned int csum_partial_copy_from_user(const char *src, char *dst, int len,
  37.                                          unsigned int sum, int *errp);
  38.  
  39. #define HAVE_CSUM_COPY_USER
  40. unsigned int csum_and_copy_to_user (const char *src, char *dst,
  41.                                     int len, int sum, int *err_ptr);
  42.  
  43. /*
  44.  * the same as csum_partial, but copies from user space (but on MIPS
  45.  * we have just one address space, so this is identical to the above)
  46.  *
  47.  * this is obsolete and will go away.
  48.  */
  49. #define csum_partial_copy_fromuser csum_partial_copy
  50. unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum);
  51.   
  52. /*
  53.  *    Fold a partial checksum without adding pseudo headers
  54.  */
  55. static inline unsigned short int csum_fold(unsigned int sum)
  56. {
  57.     __asm__("
  58.     .set    noat            
  59.     sll    $1,%0,16
  60.     addu    %0,$1
  61.     sltu    $1,%0,$1
  62.     srl    %0,%0,16
  63.     addu    %0,$1
  64.     xori    %0,0xffff
  65.     .set    at"
  66.     : "=r" (sum)
  67.     : "0" (sum)
  68.     : "$1");
  69.  
  70.      return sum;
  71. }
  72.  
  73. /*
  74.  *    This is a version of ip_compute_csum() optimized for IP headers,
  75.  *    which always checksum on 4 octet boundaries.
  76.  *
  77.  *    By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
  78.  *    Arnt Gulbrandsen.
  79.  */
  80. static inline unsigned short ip_fast_csum(unsigned char * iph,
  81.                       unsigned int ihl)
  82. {
  83.     unsigned int sum;
  84.     unsigned long dummy;
  85.  
  86.     /*
  87.      * This is for 32-bit MIPS processors.
  88.      */
  89.     __asm__ __volatile__("
  90.     .set    noreorder
  91.     .set    noat
  92.     lw    %0,(%1)
  93.     subu    %2,4
  94.     #blez    %2,2f
  95.     sll    %2,2            # delay slot
  96.  
  97.     lw    %3,4(%1)
  98.     addu    %2,%1            # delay slot
  99.     addu    %0,%3
  100.     sltu    $1,%0,%3
  101.     lw    %3,8(%1)
  102.     addu    %0,$1
  103.     addu    %0,%3
  104.     sltu    $1,%0,%3
  105.     lw    %3,12(%1)
  106.     addu    %0,$1
  107.     addu    %0,%3
  108.     sltu    $1,%0,%3
  109.     addu    %0,$1
  110.  
  111. 1:    lw    %3,16(%1)
  112.     addiu    %1,4
  113.     addu    %0,%3
  114.     sltu    $1,%0,%3
  115.     bne    %2,%1,1b
  116.     addu    %0,$1            # delay slot
  117.  
  118. 2:    .set    at
  119.     .set    reorder"
  120.     : "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (dummy)
  121.     : "1" (iph), "2" (ihl)
  122.     : "$1");
  123.  
  124.     return csum_fold(sum);
  125. }
  126.  
  127. /*
  128.  * computes the checksum of the TCP/UDP pseudo-header
  129.  * returns a 16-bit checksum, already complemented
  130.  */
  131. static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
  132.                                                unsigned long daddr,
  133.                                                unsigned short len,
  134.                                                unsigned short proto,
  135.                                                unsigned int sum)
  136. {
  137.     __asm__("
  138.     .set    noat
  139.     addu    %0,%2
  140.     sltu    $1,%0,%2
  141.     addu    %0,$1
  142.  
  143.     addu    %0,%3
  144.     sltu    $1,%0,%3
  145.     addu    %0,$1
  146.  
  147.     addu    %0,%4
  148.     sltu    $1,%0,%4
  149.     addu    %0,$1
  150.     .set    at"
  151.     : "=r" (sum)
  152.     : "0" (daddr), "r"(saddr),
  153. #ifdef __MIPSEL__
  154.         "r" ((ntohs(len)<<16)+proto*256),
  155. #else
  156.         "r" (((proto)<<16)+len),
  157. #endif
  158.         "r"(sum)
  159.     : "$1");
  160.  
  161.     return sum;
  162. }
  163.  
  164. /*
  165.  * computes the checksum of the TCP/UDP pseudo-header
  166.  * returns a 16-bit checksum, already complemented
  167.  */
  168. static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
  169.                            unsigned long daddr,
  170.                            unsigned short len,
  171.                            unsigned short proto,
  172.                            unsigned int sum)
  173. {
  174.     return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
  175. }
  176.  
  177. /*
  178.  * this routine is used for miscellaneous IP-like checksums, mainly
  179.  * in icmp.c
  180.  */
  181. static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
  182. {
  183.     return csum_fold(csum_partial(buff, len, 0));
  184. }
  185.  
  186. #define _HAVE_ARCH_IPV6_CSUM
  187. static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
  188.                              struct in6_addr *daddr,
  189.                              __u16 len,
  190.                              unsigned short proto,
  191.                              unsigned int sum) 
  192. {
  193.     __asm__("
  194.         .set    noreorder
  195.         .set    noat
  196.         addu    %0,%5        # proto (long in network byte order)
  197.         sltu    $1,%0,%5
  198.         addu    %0,$1
  199.  
  200.         addu    %0,%6        # csum
  201.         sltu    $1,%0,%6
  202.         lw    %1,0(%2)    # four words source address
  203.         addu    %0,$1
  204.         addu    %0,%1
  205.         sltu    $1,%0,$1
  206.  
  207.         lw    %1,4(%2)
  208.         addu    %0,$1
  209.         addu    %0,%1
  210.         sltu    $1,%0,$1
  211.  
  212.         lw    %1,8(%2)
  213.         addu    %0,$1
  214.         addu    %0,%1
  215.         sltu    $1,%0,$1
  216.  
  217.         lw    %1,12(%2)
  218.         addu    %0,$1
  219.         addu    %0,%1
  220.         sltu    $1,%0,$1
  221.  
  222.         lw    %1,0(%3)
  223.         addu    %0,$1
  224.         addu    %0,%1
  225.         sltu    $1,%0,$1
  226.  
  227.         lw    %1,4(%3)
  228.         addu    %0,$1
  229.         addu    %0,%1
  230.         sltu    $1,%0,$1
  231.  
  232.         lw    %1,8(%3)
  233.         addu    %0,$1
  234.         addu    %0,%1
  235.         sltu    $1,%0,$1
  236.  
  237.         lw    %1,12(%3)
  238.         addu    %0,$1
  239.         addu    %0,%1
  240.         sltu    $1,%0,$1
  241.         .set    noat
  242.         .set    noreorder"
  243.         : "=r" (sum),
  244.           "=r" (proto)
  245.         : "r" (saddr),
  246.           "r" (daddr),
  247.           "0" (htonl((__u32) (len))),
  248.           "1" (htonl(proto)),
  249.           "r"(sum)
  250.         : "$1");
  251.  
  252.     return csum_fold(sum);
  253. }
  254.  
  255. #endif /* __ASM_MIPS_CHECKSUM_H */
  256.